package core;

import java.util.Map;
import view.GUI.LabelReader;

/**
 * Combination of "interface" (public ports of the base class)
 * and implementation in the form of an internal node with
 * ports which are "compatible" with the interface (same name + compatible type).
 *
 * @author Wijnand
 */
public class InterfaceNode extends TransmitterCollectionNode {
	Node impl = null;	// null means not implemented
	
	public boolean isImplemented()
	{
		return impl != null;
	}
	
	
	/** tries to "instantiate" impl, connecting "interface" ports (this....)
	 * with impl-ports of the same name.
	 * @throws Exception if not compatible (port-name not found, wrong type)*/
	public void implement(StdNode impl) throws Exception
	{
		for (Map.Entry<String, Port> pair: this.ports.entrySet())
		{
			String portName = pair.getKey();
			Port intfPort = pair.getValue();
			Port implPort = impl.getPort(pair.getKey());
			if (implPort==null){
				throw new Exception(LabelReader.getInstance().getString("Port")+" " + portName + " " + LabelReader.getInstance().getString("NotFoundInImplementation"));
                        }
                        if (intfPort instanceof InPort)
			{
				if (!(implPort instanceof InPort)){
					throw new Exception(LabelReader.getInstance().getString("Port") + " " + pair.getKey() + " " + LabelReader.getInstance().getString("ShouldBeInPort"));
                                }
                                ((InPort)implPort).setSource(((ValueTransmitterNode)getTransmitterNode(portName)).getOutPort());
			}
			else if (intfPort instanceof OutPort)
			{
				if (!(implPort instanceof OutPort)){
					throw new Exception(LabelReader.getInstance().getString("Port")+" " + pair.getKey() + " " + LabelReader.getInstance().getString("ShouldBeOutPort"));
                                }
                                ((ValueTransmitterNode)getTransmitterNode(portName)).getInPort().setSource((OutPort)implPort);
			}
			else if (intfPort instanceof TriggerPort)
			{
				if (!(implPort instanceof TriggerPort)){
					throw new Exception(LabelReader.getInstance().getString("Port") + " " + pair.getKey() + " " + LabelReader.getInstance().getString("ShouldBeTriggerPort"));
                                }
                                ((TriggerTransmitterNode)getTransmitterNode(portName)).getDispatcherPort().addTarget((TriggerPort)implPort);
			}
			else //if (intfPort instanceof DispatcherPort)
			{
				if (!(implPort instanceof DispatcherPort)){
					throw new Exception(LabelReader.getInstance().getString("Port") + " " + pair.getKey() + " " + LabelReader.getInstance().getString("ShouldBeDispatcherPort"));
                                }
                                ((DispatcherPort)implPort).addTarget(((TriggerTransmitterNode)getTransmitterNode(portName)).getTriggerPort());
			}
			
			
		}
	}
	
	

}
